package interfaces.options;

import interfaces.inputValidation.IntegerBoundsChecker;
import interfaces.menu.options.ControlOptionsContent;
import interfaces.menu.options.OptionContent;

import main.InitGame;
import main.ResolutionHandler;

import org.jdom.Document;
import org.jdom.Element;

import com.jme.math.FastMath;

import fileHandling.SettingsLoader;
import fileHandling.language.Lang;
import fileHandling.language.LanguageLoader;
import fileHandling.language.options.OptionValues;

public class OptionWidgetFactory {
	
	public enum OptionType 
		{ Int, Float, Language, Level, Bool, Key, Lang, Resolution, Antialiasing, TripleFilter, Text, TextureFilter }
	
	public static final String UI_OPTIONS_DIR = "data/ui/options/";
	
	public static final String TYPE = "type";
	public static final String VALUES = "values";
	public static final String MIN = "min";
	public static final String MAX = "max";
	
	private Element root;
	private OptionContent optionContent;
	
	public OptionWidgetFactory(String fileName, OptionContent optionContent) {
		this.optionContent = optionContent;
		
		Document doc = SettingsLoader.getDocument(UI_OPTIONS_DIR + fileName);
		root = doc.getRootElement();
	}
	
	public OptionWidget createWidget(Lang description, String initValue) {
		Element elem = getElement(description.toString());
		OptionType type = getType(elem);
		
		switch(type) {
			case Bool: return createBool(initValue, description);
			case Float: return createFloat(initValue, description);
			case Int: return createInt(initValue, description, getMin(elem), getMax(elem));
			case Level: return createLevel(initValue, description);
			case Key: return createKey(initValue, description);
			case Lang: return createLang(initValue, description, getValues(elem));
			case Language: return createLanguage(initValue, description);
			case Antialiasing: return createAntialiasing(initValue, description);
			case Resolution: return createResolution(initValue, description);
			case TripleFilter: return createTriple(initValue, description);
			case Text: return createText(initValue, description);
			case TextureFilter: return createTextureFilter(initValue, description);
		}
		return null;
	}
	
	public OptionType getType(Element element) {
		return OptionType.valueOf(element.getAttributeValue(TYPE));
	}
	
	public Element getElement(String description) {
		return root.getChild(description);
	}
	
	public String[] getValues(Element elem) {
		String[] v = elem.getAttributeValue(VALUES).split(",");
		String[] values = new String[v.length];
		for(int i = 0; i < v.length; i++) {
			values[i] = OptionValues.valueOf(v[i]).toString();
		}
		
		return values;
	}
	
	public int getMin(Element elem) { return Integer.valueOf(elem.getAttributeValue(MIN)).intValue(); }
	
	public int getMax(Element elem) { return Integer.valueOf(elem.getAttributeValue(MAX)).intValue(); }
	
	private CheckBoxOptionWidget createBool(String initValue, Lang description) {
		return new CheckBoxOptionWidget(initValue, description);
	}
	
	private SliderOptionWidget createFloat(String initValue, Lang description) {
		return new SliderOptionWidget(initValue, description);
	}
	
	private TextEditorOptionWidget createInt(String initValue, Lang description, int min, int max) {
		IntegerBoundsChecker checker = new IntegerBoundsChecker(min, max);
		return new TextEditorOptionWidget(initValue, description, checker);
	}
	
	private ComboBoxOptionWidget createLevel(String initValue, Lang description) {
		String high = OptionValues.High.toString();
		String medium = OptionValues.Medium.toString();
		String low = OptionValues.Low.toString();
		String[] values = new String[] { high, medium, low };
		return new ComboBoxOptionWidget(initValue, description, values, high, medium, low);
	}
	
	private KeyOptionWidget createKey(String initValue, Lang description) {
		return new KeyOptionWidget(initValue, description, (ControlOptionsContent)optionContent, optionContent.getMenu());
	}
	
	private ComboBoxOptionWidget createLang(String initValue, Lang description, String[] values) {
		return new ComboBoxOptionWidget(initValue, description, values, null, null, null);
	}
	
	private ComboBoxOptionWidget createLanguage(String initValue, Lang description) {
		String[] values = LanguageLoader.getInstalledLanguages();
		return new ComboBoxOptionWidget(initValue, description, values, null, null, null);
	}
	
	private ComboBoxOptionWidget createAntialiasing(String initValue, Lang description) {
		String off = OptionValues.Off.toString();
		int max = InitGame.MAX_SAMPLES;
		if(max == 0) return new ComboBoxOptionWidget(initValue, description, new String[] { off }, off, off, off);
		
		int entries = 1;
		int temp = max;
		while(temp >= 2) {
			temp /= 2;
			entries++;
		}
		
		String[] values = new String[entries];
		values[0] = off;
		int s = 2;
		for(int i = 1; i < entries; i++, s *= 2) {
			values[i] = s + "x";
		}
		
		String high = values[entries - 1];
		
		int m = (int)FastMath.floor(entries / 2f);
		String medium = values[m];
		
		return new ComboBoxOptionWidget(initValue, description, values, high, medium, off);
	}
	
	private ComboBoxOptionWidget createResolution(String initValue, Lang description) {
		String[] values = ResolutionHandler.get().getSortedResolutions();
		return new ComboBoxOptionWidget(initValue, description, values, null, null, null);
	}
	
	private OptionWidget createTriple(String initValue, Lang description) {
		String dont = OptionValues.Dont_Show.toString();
		String only = OptionValues.Show_Only.toString();
		String matter = OptionValues.Doesnt_Matter.toString();
		String[] values = new String[] { dont, only, matter };
		return new ComboBoxOptionWidget(initValue, description, values, null, null, null);
	}
	
	private OptionWidget createText(String initValue, Lang description) {
		return new TextEditorOptionWidget(initValue, description);
	}
	
	private OptionWidget createTextureFilter(String initValue, Lang description) {
		String bil = OptionValues.Bilinear.toString();
		String tril = OptionValues.Trilinear.toString();
		String[] values = new String[] { bil, tril };
		return new ComboBoxOptionWidget(initValue, description, values, tril, tril, bil);
	}
}